/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
package org.unidata.mdm.rest.v1.dq.core.converter;

import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.unidata.mdm.core.type.data.ArrayAttribute;
import org.unidata.mdm.core.type.data.Attribute;
import org.unidata.mdm.core.type.data.Attribute.AttributeType;
import org.unidata.mdm.core.type.data.SimpleAttribute;
import org.unidata.mdm.dq.core.dto.CleanseFunctionResult;
import org.unidata.mdm.dq.core.type.cleanse.CleanseFunctionOutputParam;
import org.unidata.mdm.rest.system.converter.Converter;
import org.unidata.mdm.rest.v1.dq.core.ro.ExecuteFunctionResultRO;
import org.unidata.mdm.rest.v1.dq.core.ro.constant.ArrayConstantRO;
import org.unidata.mdm.rest.v1.dq.core.ro.constant.ArrayValueRO;
import org.unidata.mdm.rest.v1.dq.core.ro.constant.SingleConstantRO;
import org.unidata.mdm.rest.v1.dq.core.ro.constant.SingleValueRO;
import org.unidata.mdm.rest.v1.dq.core.ro.execute.FunctionExecutionParamRO;

/**
 * @author Mikhail Mikhailov on Feb 9, 2021
 */
public class ExecuteFunctionResponseConverter extends Converter<CleanseFunctionResult, ExecuteFunctionResultRO> {
    /**
     * DQE converter.
     */
    private static final DataQualityErrorConverter DATA_QUALITY_ERROR_CONVERTER = new DataQualityErrorConverter();
    /**
     * Constructor.
     * @param to
     * @param from
     */
    public ExecuteFunctionResponseConverter() {
        super(ExecuteFunctionResponseConverter::convert, null);
    }

    public static ExecuteFunctionResultRO convert(CleanseFunctionResult in) {

        ExecuteFunctionResultRO out = new ExecuteFunctionResultRO();
        out.setResults(in.getOutputParams().stream()
            .map(ExecuteFunctionResponseConverter::convert)
            .filter(Objects::nonNull)
            .collect(Collectors.toList()));

        out.setSuccess(CollectionUtils.isEmpty(in.getErrors()));
        out.setErrors(DATA_QUALITY_ERROR_CONVERTER.to(in.getErrors()));

        return out;
    }

    private static FunctionExecutionParamRO convert(CleanseFunctionOutputParam in) {

        if (Objects.isNull(in) || in.isEmpty()) {
            return null;
        }

        FunctionExecutionParamRO result = new FunctionExecutionParamRO();
        result.setPortName(in.getPortName());

        Attribute attr = in.getSingleton();
        if (attr.getAttributeType() == AttributeType.ARRAY) {

            ArrayAttribute<?> aa = attr.narrow();
            result.setConstant(new ArrayConstantRO(new ArrayValueRO(aa.getDataType().name(), aa.toArray())));
        } else if (attr.getAttributeType() == AttributeType.SIMPLE) {

            SimpleAttribute<?> sa = attr.narrow();
            result.setConstant(new SingleConstantRO(new SingleValueRO(sa.getDataType().name(), sa.getValue())));
        }

        return result;
    }
}
